from xpy3lib.XRetryableQuery import XRetryableQuery
from xpy3lib.XRetryableSave import XRetryableSave
from sicost.AbstractDPJob import AbstractDPJob
import sys, datetime, json, time
import pandas as pd
import numpy as np
from xpy3lib.utils.XDataFrameUtils import XDataFrameUtils
from pytsdb import xtsdb
from numpy import array


class ReplenishJob(AbstractDPJob):
    MESSAGE_4_GET_TOKEN_SUCCED = '获取Token成功'
    MESSAGE_4_GET_TOKEN_FAILED = '获取Token失败'

    def __init__(self,
                 p_starttime=None,
                 p_endtime=None,
                 p_tag=None,
                 p_reasonableMaximums=None,
                 p_reasonableBounds=None):

        super(ReplenishJob, self).__init__()

        self.starttime = p_starttime
        self.endtime = p_endtime
        self.tag = p_tag
        self.reasonableMaximums = p_reasonableMaximums
        self.reasonableBounds = p_reasonableBounds

        pass

    def execute(self):
        return self.do_execute()

    def do_execute(self):
        super(ReplenishJob, self).do_execute()
        """
        补数据Job
        通过JSON传入参数tag，startTime，endTime得到原始数据
        去tsDB查询得到原始数据
        将其转换成dataframe格式
        """
        def __cal_search_data_from_tsdb(collector_name, tag_names, start_time, end_time, tag):
            try:
                r = xdb.getHistoryByTagNames(collector_name, tag_names, start_time=start_time, end_time=end_time,
                                             minutes=5)
                message = '从tsdb获取' + tag + '数据成功'
                success = True
            except Exception as e:
                message = '从tsdb获取' + tag + '数据失败'
                success = False
                df = None
                current_cursor_mask = None
                m = None
                return success, message, df, current_cursor_mask, m

            row_data = r[self.tag]
            m = len(row_data['records'])
            print(m)
            if m == 0:
                df = None
                current_cursor_mask = row_data['next_cursor_mask']
                current_cursor_mask = int(current_cursor_mask)
                success = True
                message = 'no data'
                return success, message, df, current_cursor_mask, m
            # m为数据条数，应该可以直接转df
            # m=1000超出了上限。需要循环出所有数据
            df = pd.DataFrame(row_data['records'])
            current_cursor_mask = row_data['next_cursor_mask']
            current_cursor_mask = int(current_cursor_mask)
            success = True
            message = 'has data'
            # 最后一条数据的时间毫秒数+1
            # 看数据默认从开始时间开始
            return success, message, df, current_cursor_mask, m
    ############################################################################
        try:
            # 获取Token
            # xdb = xtsdb(host='10.70.248.146', user='admin@BGTATOADMN01', pswd='admin')
            # xdb = xtsdb(host='10.70.248.213', user='admin@BGTATOADMN01', pswd='FdS8_wq12A')
            # 宝
            # xdb = xtsdb(host='10.70.248.213', user='admin@BGTATOADMN01', pswd='FdS8_wq12A')
            # 梅
            xdb = xtsdb(host='10.70.248.213', user='admin@BGTMTOADMN01', pswd='ZAQop_yg')

            message = ReplenishJob.MESSAGE_4_GET_TOKEN_SUCCED
            success = True
        except Exception as e:
            # NOTE failed if fetch token failed, no re-try.
            message = ReplenishJob.MESSAGE_4_GET_TOKEN_FAILED
            success = False
            max_time = None
            min_time = None
            df_original = None
            anytag_has_data = None
            return anytag_has_data, success, message, df_original

        #
        print([self.tag])
        try:
            r = xdb.getHistoryByTagNames('BGTMTOAE01', [self.tag],
                                         start_time=self.starttime, end_time=self.endtime, minutes=5)
            message = '从tsdb获取' + self.tag + '数据成功'
            success = True
            anytag_has_data = 1
        except Exception as e:
            message = '从tsdb获取' + self.tag + '数据失败'
            success = False
            anytag_has_data = 0
            df_original = None
            return anytag_has_data, success, message, df_original

        row_data = r[self.tag]
        m = len(row_data['records'])
        if m == 0:
            df_original = None
            success = True
            message = '该时间范围内' + self.tag + '无数据'
            anytag_has_data = 0
            return anytag_has_data, success, message, df_original

        print("row_data的类型", type(row_data))
        print(row_data['next_cursor_mask'])
        current_cursor_mask0 = row_data['next_cursor_mask']
        current_cursor_mask0 = int(current_cursor_mask0)

        # m = len(row_data['records'])
        # print(m)
        # if n < 1000:
        if current_cursor_mask0 >= self.endtime:
            # 数据条数不超过1000，不需要循环取全，直接生成df
            df = pd.DataFrame(row_data['records'])
        else:
            # 数据条数为1000，被limit了，需要循环取全
            success, message, df1, current_cursor_mask1, m1 = __cal_search_data_from_tsdb(collector_name='BGTMTOAE01',
                                                                                          tag_names=[self.tag],
                                                                                          start_time=self.starttime,
                                                                                          end_time=self.endtime,
                                                                                          tag=self.tag)
            if success is False:
                message = '从tsdb获取' + self.tag + '数据失败'
                success = False
                anytag_has_data = 0
                df_original = None
                return anytag_has_data, success, message, df_original

            while current_cursor_mask1 < self.endtime:
                success, message, df2, current_cursor_mask2, m2 = __cal_search_data_from_tsdb(
                    collector_name='BGTMTOAE01', tag_names=[self.tag],
                    start_time=int(current_cursor_mask1),
                    end_time=self.endtime, tag=self.tag)
                if success is False:
                    df_original = None
                    return anytag_has_data, success, message, df_original
                if m2 == 0:
                    current_cursor_mask1 = current_cursor_mask2
                    continue
                else:
                    df1 = pd.concat([df1, df2], ignore_index=True)
                    df1 = df1.reset_index(drop=True)
                    current_cursor_mask1 = current_cursor_mask2

            df = df1
        print(df)
        df.drop(['quality'], axis=1, inplace=True)
        df.drop(['id'], axis=1, inplace=True)
        df.drop(['type'], axis=1, inplace=True)
        # df['value'] = pd.factorize(df['value'])[0].astype(float)
        df['value'] = df['value'].astype(float)

        # 读取数据集
        # df1 = XDataFrameUtils.excel2dataframe(p_excel_file_path='test_20221205.xlsx')
        # 将字段Datetime数据类型转换为日期类型
        # df['datetime'] = pd.to_datetime(df['datetime'], format="%Y-%m-%d %H:%M:%S")

        df0 = df

        def __cal_max_min(x):

            if x.value >= float(self.reasonableBounds) and x.value <= float(self.reasonableMaximums):
                rst = 1
            else:
                rst = 0
            return rst

        df0['type'] = df0.apply(lambda x: __cal_max_min(x), axis=1)
        df00 = df0[df0['type'] == 1]
        df00['timestamp0'] = df00["timestamp"]
        df00['timestamp1'] = df00["timestamp0"].shift(-1)

        df00['timestamp1'].fillna(value=0.0, inplace=True)
        def __cal_gap(x):

            if x.timestamp1 != 0.0:
                rst = round((x.timestamp1 - x.timestamp0) / 1000)
            else:
                rst = 0
            return rst

        df00['gap'] = df00.apply(lambda x: __cal_gap(x), axis=1)

        mode = df00['gap'].mode()
        mode = mode[0]
        judge = (mode - 1) * 2

        # def __cal_judge_code(x):
        #
        #     if x.gap < judge:
        #         rst = 0
        #     else:
        #         rst = 1
        #     return rst
        # df00['judge_code'] = df00.apply(lambda x: __cal_judge_code(x), axis=1)
        df000 = df00

        for index_df000, row_df000 in df000.iterrows():
            tmp_gap = df000.loc[index_df000, 'gap']
            tmp_timestamp0 = df000.loc[index_df000, 'timestamp0']
            tmp_timestamp1 = df000.loc[index_df000, 'timestamp1']
            if tmp_gap > judge:
                need_replenish_num = np.floor(tmp_gap/mode)
                new_gap = int((tmp_timestamp1-tmp_timestamp0) / (need_replenish_num+1))
                need_replenish_num = int(need_replenish_num)
                for i in range(need_replenish_num):
                    print(i)
                    if i < 1:
                        continue
                    new_timestamp = tmp_timestamp0 + new_gap * i
                    new = pd.DataFrame({'timestamp': new_timestamp,
                                        'value': None,
                                        'timestamp0': None,
                                        'timestamp1': None,
                                        'gap': None
                                        }, index=[0]
                                       )
                    df00 = df00.append(new, ignore_index=True)

        df00.drop(['timestamp0'], axis=1, inplace=True)
        df00.drop(['timestamp1'], axis=1, inplace=True)
        df00.drop(['gap'], axis=1, inplace=True)

















        def __cal_timestamp2datetime(x):

            ret2 = time.localtime(x.timestamp / 1000)
            rst = time.strftime("%Y-%m-%d %H:%M:%S", ret2)

            return rst

        df00['datetime'] = df00.apply(lambda x: __cal_timestamp2datetime(x), axis=1)
        print(df)



        df00['datetime'] = pd.to_datetime(df00['datetime'], format="%Y-%m-%d %H:%M:%S")

        d = df00.sort_values('timestamp')



        d['timestampindex'] = d['timestamp']
        d.set_index('timestampindex', inplace=True)
        # d['value'] = d['value'].interpolate(method='quadratic')
        d['value'] = d['value'].interpolate(method='linear')
        d = d.reset_index(drop=True)
        d['datetime_new'] = d['datetime'].astype("string")

        d['timestamp'].fillna(value=0.0, inplace=True)

        def __cal_datetime2timestamp(x):
            if x.timestamp != 0.0:
                rst = x.timestamp
            else:
                timeArray = time.strptime(x.datetime_new, "%Y-%m-%d %H:%M:%S")
                ret = int(time.mktime(timeArray))
                rst = ret * 1000
            return rst

        d['timestamp_new'] = d.apply(lambda x: __cal_datetime2timestamp(x), axis=1)

        d.drop(['type'], axis=1, inplace=True)
        d.drop(['datetime_new'], axis=1, inplace=True)
        d.drop(['timestamp'], axis=1, inplace=True)
        d.rename(columns={'timestamp_new': 'timestamp'}, inplace=True)
        df_original = d
        print('finish')
        return anytag_has_data, success, message, df_original